此篇再延續上篇,詳細紀錄一下三種宣告方式的不同。
在ES6之前只有var的宣告方式;在ES6之後,即新增了let & const兩種方式:
var
- 宣告一個可隨意更改內容的變數 - 函式作用域 (function-level scope)
⇒ 只有在「函式」裡可以看得到,特性相當於全域變數
不會受限在區域(block scope)內,可能會汙染全域變數。不管哪個作用域(Scope)都可以存取,可以重複宣告。(若沒有放在函式裡宣告,區域變數會覆蓋全域變數)
範例如下:
var a = 5;
if (true) {
var a = 10; //區域變數覆蓋全域變數!!
console.log(a); //結果為10
}
console.log(a); //結果為10
再看以下範例,若在一個 函式
內使用 var 宣告變數時,那這個變數就變成了一個區域變數,只有在函式內才看得到。
var a = 5
function MyFunction() {
if (true) {
var a = 10;
}
console.log(a); // 結果為10
}
MyFunction();
console.log(a); // 結果為5
let
- 宣告一個可隨意更改內容的區域變數-區塊作用域 (block-level scope)
⇒ 只有在「區塊」裡面才看得到,即只有在 {}花括號
裡的才是它的作用域範圍。
所宣告的變項只有在區域內(block scope)有效,不會產生全域變數,也就是 { } 包住的區域,一但離開 { } 範圍,這個變數就不會被存取到,也無法在同一層 Block 重複宣告變數。
var b = 6;
if (true) {
let b = 20;
console.log(b); //出現20
}
console.log(b); //出現6 即為{}外的變數=6
無法在同一層 Block 重複宣告變數:
let a = 6;
let a = 20;
console.log(a);
//出現錯誤:Identifier 'a' has already been declared**
但是如果 let
宣告的變數在 不同層的Block ,就不會報錯:
let a = 6;
if (true) {
let a = 20;
console.log(a); //出現20
}
console.log(a); //出現6
const
- 宣告一個只可讀取的不可變常數-區塊作用域 (block-level scope)
⇒ 只有在「區塊」裡面才看得到,即只有在 {}花括號
裡的才是它的作用域範圍。
宣告後不能更改值,否則會報錯
const a = 123;
a = 456; // TypeError: Assignment to constant variable.
一宣告時就必定要指定給值,否則會報錯
const b ;
b = 456; //SyntaxError: Missing initializer in const declaration
只要無宣告變數直接賦值就會被視為 全域變數
(寫在全域環境的 var、let、const 變數同樣可以視為全域變數)
另一點差異是 能不能透過 delet 操作刪除變數
,先來看下面程式碼:
//未宣告
a = 6;
delete a; //true
console.log(a); //a is not defined
//宣告
var b = 10;
delete b; //false
console.log(b); //10;
從以上範例可以發現,有使用var宣告的b是不可被刪除的,而未宣告的a可以被刪除。
這是因為如果沒有經過var宣告的變數「會被當作物件屬性」的方式新增,因此才會強烈建議變數一定要宣告,否則可輕易被刪除的變數是很容易出現出問題的。
我們可以透過Object.getOwnPropertyDescriptor
來獲取全域屬性: (可參考MDN)
//未宣告
a = 6;
Object.getOwnPropertyDescriptor(window, 'a')
//{value: 6, writable: true, enumerable: true, configurable: true}
//宣告
var b = 10;
Object.getOwnPropertyDescriptor(window, 'b')
//{value: 10, writable: true, enumerable: true, configurable: false}
由上方a, b 變數的屬性可發現,兩者的配置性configurable有所不同。而configurable為false的代表此物件屬性無法被刪除,configurable為true的則反之。
因此,經過var宣告的變數是不能被delete的。
參考來源:
https://hsiangfeng.github.io/javascript/20200425/539985371/
https://ithelp.ithome.com.tw/articles/10191549
https://tw.alphacamp.co/blog/javascript-var-let-const